<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Face landmark detection in an image</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../de/d27/tutorial_table_of_content_face.html">Tutorials for face module</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Face landmark detection in an image </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="../../facereg.jpg" alt="facereg.jpg"/>
</div>
<p>This application lets you detect landmarks of detected faces in an image. You can detect landmarks of all the faces found in an image and use them further in various applications like face swapping, face averaging etc. This functionality is now available in OpenCV.</p>
<div class="fragment"><div class="line">// Command to be typed for running the sample</div><div class="line">./sampleDetectLandmarks -file=trained_model.dat -face_cascade=lbpcascadefrontalface.xml -image=/path_to_image/image.jpg</div></div><!-- fragment --> <h3>Description of command parameters {tutorial_face_training_parameters}</h3>
<blockquote class="doxtable">
<ul>
<li><b>model_filename</b> f : (REQUIRED) A path to binary file storing the trained model which is to be loaded [example - /data/file.dat]</li>
<li><b>image</b> i : (REQUIRED) A path to image in which face landmarks have to be detected.[example - /data/image.jpg]</li>
<li><b>face_cascade</b> c : (REQUIRED) A path to the face cascade xml file which you want to use as a face detector. </li>
</ul>
</blockquote>
<h2>Understanding code </h2>
<div class="image">
<img src="../../d.png" alt="d.png"/>
</div>
<p>This tutorial will explain the sample code for face landmark detection. Jumping directly to the code :</p>
<div class="fragment"><div class="line">CascadeClassifier face_cascade;</div><div class="line">face_cascade.load(cascade_name);</div><div class="line"></div><div class="line">Mat img = imread(image);</div><div class="line">Ptr&lt;Facemark&gt; facemark = createFacemarkKazemi());</div><div class="line">facemark-&gt;loadModel(filename);</div><div class="line">cout&lt;&lt;&quot;Loaded model&quot;&lt;&lt;endl;</div></div><!-- fragment --><p>The above code creates a CascadeClassifier to detect face regions, and an instance of the face landmark detection class. We need to load a pretrained model for face landmark detection, and a cascade file for the face detection. It also loads the image in which landmarks have to be detected.</p>
<div class="fragment"><div class="line">vector&lt;Rect&gt; faces;</div><div class="line">resize(img,img,Size(460,460),0,0,INTER_LINEAR_EXACT);</div><div class="line"></div><div class="line">Mat gray;</div><div class="line">std::vector&lt;Rect&gt; faces;</div><div class="line">if(img.channels()&gt;1){</div><div class="line">    cvtColor(img.getMat(),gray,COLOR_BGR2GRAY);</div><div class="line">}</div><div class="line">else{</div><div class="line">    gray = img.getMat().clone();</div><div class="line">}</div><div class="line">equalizeHist( gray, gray );</div><div class="line"></div><div class="line">face_cascade.detectMultiScale( gray, faces, 1.1, 3,0, Size(30, 30) );</div></div><!-- fragment --><p>After doing some preprocessing, we first have to detect possible face regions (which will be stored in a <code>vector&lt;Rect&gt;</code>. Also, the image is resized to a smaller size as processing speed is faster with small images.</p>
<div class="fragment"><div class="line">vector&lt; vector&lt;Point2f&gt; &gt; shapes;</div><div class="line"></div><div class="line">if (facemark-&gt;fit(img,faces,shapes))</div><div class="line">{</div><div class="line">    for ( size_t i = 0; i &lt; faces.size(); i++ )</div><div class="line">    {</div><div class="line">        cv::rectangle(img,faces[i],Scalar( 255, 0, 0 ));</div><div class="line">    }</div><div class="line">    for (unsigned long i=0;i&lt;faces.size();i++){</div><div class="line">        for(unsigned long k=0;k&lt;shapes[i].size();k++)</div><div class="line">            cv::circle(img,shapes[i][k],5,cv::Scalar(0,0,255),FILLED);</div><div class="line">    }</div><div class="line">    namedWindow(&quot;Detected_shape&quot;);</div><div class="line">    imshow(&quot;Detected_shape&quot;,img);</div><div class="line">    waitKey(0);</div><div class="line">}</div></div><!-- fragment --><p>It then creates a vector of vector to store shapes for each face detected. The above code calls the function fit to get shapes of all detected faces in the image and then draws the rectangles bounding the faces and marks the desired landmarks.</p>
<h3>Detection Results</h3>
<div class="image">
<img src="../../ab.jpg" alt="ab.jpg"/>
</div>
<div class="image">
<img src="../../ab-1.jpg" alt="ab-1.jpg"/>
</div>
 </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:38 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
